package com.lzy.aop;

import com.lzy.dto.UserDto;
import com.lzy.entity.OperateLog;
import com.lzy.entity.Student;
import com.lzy.entity.Result;
import com.lzy.entity.User;
import com.lzy.mapper.OperateLogMapper;
import com.lzy.vo.TeacherWithClassVO;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

/**
 * 操作日志切面
 * 自动拦截学生和教师的增删改操作并记录日志
 */
@Aspect
@Component
public class OperateLogAspect {
    
    private static final Logger log = LoggerFactory.getLogger(OperateLogAspect.class);
    
    @Autowired
    private OperateLogMapper operateLogMapper;
    
    // 操作类型常量
    private static final int OPERATE_CREATE = 1;// 1-新增
    private static final int OPERATE_UPDATE = 2;// 2-修改
    private static final int OPERATE_DELETE = 3;// 3-删除
    
    // 目标类型常量
    private static final int TARGET_STUDENT = 1;//  1-学生
    private static final int TARGET_TEACHER = 2;// 2-教师
    private static final int TARGET_USER = 3;// 3-用户
    
    //定义切点：学生增加操作
    @Pointcut("execution(* com.lzy.service.impl.StudentServiceImpl.createStudent(..))")
    public void studentCreatePointcut() {}
    
    // 定义切点：学生更新操作
    @Pointcut("execution(* com.lzy.service.impl.StudentServiceImpl.updateStudent(..))")
    public void studentUpdatePointcut() {}
    

    //定义切点：学生删除操作
    @Pointcut("execution(* com.lzy.service.impl.StudentServiceImpl.delStudent(..))")
    public void studentDeletePointcut() {}
    
    //定义切点：教师增加操作
    @Pointcut("execution(* com.lzy.service.impl.TeacherServiceImpl.addTeacher(..))")
    public void teacherCreatePointcut() {}
    
    //定义切点：教师更新操作
    @Pointcut("execution(* com.lzy.service.impl.TeacherServiceImpl.updateTeacher(..))")
    public void teacherUpdatePointcut() {}
    

    //定义切点：教师删除操作
    @Pointcut("execution(* com.lzy.service.impl.TeacherServiceImpl.removeById(..))")
    public void teacherDeletePointcut() {}

    //用户新增操作
    @Pointcut("execution(* com.lzy.service.impl.UserServiceImpl.register(..)) || execution(* com.lzy.service.impl.UserServiceImpl.createUser(..))")
    public void userRegisterPointcut() {}

    //用户更新操作
    @Pointcut("execution(* com.lzy.service.impl.UserServiceImpl.updateUser(..))")
    public void userUpdatePointcut() {}

    // 用户删除操作
    @Pointcut("execution(* com.lzy.service.impl.UserServiceImpl.deleteUser(..))")
    public void userDeletePointcut() {}
    
    /**
     * 学生新增操作日志记录
     */
    @AfterReturning(pointcut = "studentCreatePointcut() && args(student)", returning = "result")
    public void afterStudentCreate(JoinPoint joinPoint, Student student, Object result) {
        try {
            if (result instanceof Boolean && (Boolean) result && student != null) {
                saveStudentLog(student, OPERATE_CREATE, "新增学生信息");
            }
        } catch (Exception e) {
            log.error("记录学生新增日志异常", e);
        }
    }
    
    /**
     * 学生更新操作日志记录
     */
    @AfterReturning(pointcut = "studentUpdatePointcut() && args(student)", returning = "result")
    public void afterStudentUpdate(JoinPoint joinPoint, Student student, Object result) {
        try {
            if (result instanceof Boolean && (Boolean) result && student != null) {
                saveStudentLog(student, OPERATE_UPDATE, "更新学生信息");
            }
        } catch (Exception e) {
            log.error("记录学生更新日志异常", e);
        }
    }
    
    /**
     * 学生删除操作日志记录
     */
    @AfterReturning(pointcut = "studentDeletePointcut() && args(id)", returning = "result")
    public void afterStudentDelete(JoinPoint joinPoint, Integer id, Object result) {
        try {
            if (result instanceof Boolean && (Boolean) result && id != null) {
                OperateLog operateLog = new OperateLog();
                operateLog.setOperateType(OPERATE_DELETE);
                operateLog.setTargetType(TARGET_STUDENT);
                operateLog.setTargetId(id);
                operateLog.setTargetName("已删除");
                operateLog.setTargetNum("已删除");
                operateLog.setContent("删除学生信息");
                operateLog.setCreateTime(LocalDateTime.now());
                
                operateLogMapper.insert(operateLog);
                log.info("记录学生删除日志: {}", operateLog);
            }
        } catch (Exception e) {
            log.error("记录学生删除日志异常", e);
        }
    }
    
    /**
     * 保存学生操作日志的公共方法
     */
    private void saveStudentLog(Student student, int operateType, String content) {
        OperateLog operateLog = new OperateLog();
        operateLog.setOperateType(operateType);
        operateLog.setTargetType(TARGET_STUDENT);
        operateLog.setTargetId(student.getId());
        operateLog.setTargetName(student.getName());
        operateLog.setTargetNum(student.getStuNo());
        operateLog.setContent(content);
        operateLog.setCreateTime(LocalDateTime.now());
        
        operateLogMapper.insert(operateLog);
        log.info("记录学生操作日志: {}", operateLog);
    }
    
    /**
     * 教师新增操作日志记录
     */
    @AfterReturning(pointcut = "teacherCreatePointcut() && args(teacherVO)", returning = "result")
    public void afterTeacherCreate(JoinPoint joinPoint, TeacherWithClassVO teacherVO, Object result) {
        try {
            if (result instanceof Result && ((Result) result).getCode() == 200 && teacherVO != null) {
                saveTeacherLog(teacherVO, OPERATE_CREATE, "新增教师信息");
            }
        } catch (Exception e) {
            log.error("记录教师新增日志异常", e);
        }
    }
    
    /**
     * 教师更新操作日志记录
     */
    @AfterReturning(pointcut = "teacherUpdatePointcut() && args(teacherVO)", returning = "result")
    public void afterTeacherUpdate(JoinPoint joinPoint, TeacherWithClassVO teacherVO, Object result) {
        try {
            if (result instanceof Boolean && (Boolean) result && teacherVO != null) {
                saveTeacherLog(teacherVO, OPERATE_UPDATE, "更新教师信息");
            }
        } catch (Exception e) {
            log.error("记录教师更新日志异常", e);
        }
    }
    
    /**
     * 教师删除操作日志记录
     */
    @AfterReturning(pointcut = "teacherDeletePointcut() && args(id)", returning = "result")
    public void afterTeacherDelete(JoinPoint joinPoint, Integer id, Object result) {
        try {
            if (result instanceof Boolean && (Boolean) result && id != null) {
                OperateLog operateLog = new OperateLog();
                operateLog.setOperateType(OPERATE_DELETE);
                operateLog.setTargetType(TARGET_TEACHER);
                operateLog.setTargetId(id);
                operateLog.setTargetName("已删除");
                operateLog.setTargetNum("已删除");
                operateLog.setContent("删除教师信息");
                operateLog.setCreateTime(LocalDateTime.now());
                
                operateLogMapper.insert(operateLog);
                log.info("记录教师删除日志: {}", operateLog);
            }
        } catch (Exception e) {
            log.error("记录教师删除日志异常", e);
        }
    }
    
    /**
     * 保存教师操作日志的公共方法
     */
    private void saveTeacherLog(TeacherWithClassVO teacherVO, int operateType, String content) {
        OperateLog operateLog = new OperateLog();
        operateLog.setOperateType(operateType);
        operateLog.setTargetType(TARGET_TEACHER);
        operateLog.setTargetId(teacherVO.getId());
        operateLog.setTargetName(teacherVO.getTName());
        operateLog.setTargetNum(teacherVO.getTNum());
        operateLog.setContent(content);
        operateLog.setCreateTime(LocalDateTime.now());
        
        operateLogMapper.insert(operateLog);
        log.info("记录教师操作日志: {}", operateLog);
    }

    // 用户新增操作日志记录
    @AfterReturning(pointcut = "userRegisterPointcut() && args(userDto)", returning = "result")
    public void afterUserRegister(JoinPoint joinPoint, UserDto userDto, Object result) {
        try {
            if (result instanceof Result && ((Result) result).getCode() == 200 && userDto != null) {
                saveUserLog(userDto, OPERATE_CREATE, "新增用户信息");
            }
        } catch (Exception e) {
            log.error("记录用户新增日志异常", e);
        }
    }

    // 用户更新操作日志记录
    @AfterReturning(pointcut = "userUpdatePointcut() && args(userDto)", returning = "result")
    public void afterUserUpdate(JoinPoint joinPoint, UserDto userDto, Object result) {
        try {
            if (result instanceof Result && ((Result) result).getCode() == 200 && userDto != null) {
                saveUserLog(userDto, OPERATE_UPDATE, "更新用户信息");
            }
        } catch (Exception e) {
            log.error("记录用户更新日志异常", e);
        }
    }

    // 用户删除操作日志记录
    @AfterReturning(pointcut = "userDeletePointcut() && args(id)", returning = "result")
    public void afterUserDelete(JoinPoint joinPoint, Integer id, Object result) {
        try {
            if (result instanceof Boolean && (Boolean) result && id != null) {
                OperateLog operateLog = new OperateLog();
                operateLog.setOperateType(OPERATE_DELETE);
                operateLog.setTargetType(TARGET_USER);
                operateLog.setTargetId(id);
                operateLog.setTargetName("已删除");
                operateLog.setTargetNum("已删除");
                operateLog.setContent("删除用户信息");
                operateLog.setCreateTime(LocalDateTime.now());

                operateLogMapper.insert(operateLog);
                log.info("记录用户删除日志: {}", operateLog);
            }
        } catch (Exception e) {
            log.error("记录用户删除日志异常", e);
        }
    }

    // 保存用户操作日志的公共方法
    private void saveUserLog(UserDto userDto, int operateType, String content) {
        OperateLog operateLog = new OperateLog();
        operateLog.setOperateType(operateType);
        operateLog.setTargetType(TARGET_USER);
        operateLog.setTargetId(userDto.getId());
        operateLog.setTargetName(userDto.getUserName());
        operateLog.setTargetNum(userDto.getUserName());
        operateLog.setContent(content);
        operateLog.setCreateTime(LocalDateTime.now());

        operateLogMapper.insert(operateLog);
        log.info("记录用户操作日志: {}", operateLog);
    }
} 